#include "mainwindowimpl.h"

#define EM_LS GSL_CONST_MKSA_SPEED_OF_LIGHT //2.99792458e8		//скорость света

bool MainWindowImpl::on_but_diag_clicked()
{
    isSec=0;
    QString str,sig;
    int NPt,sopr=1;	//NPt: number of points through teta; sopr: sign of image patr
    double ampl,arg;    //control of sopr-change
    double param0,paramN, dPar;
    Structure *toFt;
    __complex__ double EIt; //complex coordinates of tensity vector
    gsl_complex EItog[3], vectorE; 	//complex coordinates of tensity vector
    toFt=&ft;
    initCalc(); //Initialization
    //! on_but_printParam_clicked(); //print
    NPt=boxNdiag->value();
    progress_int->setMaximum(NPt);
    //begin of evaluating
    param0=boxParam0->value();
    paramN=boxParamN->value();
    Vainshtein vt;
    if(method==3)
    {
        if (param!=1)
        {
            QMessageBox::information(0, qApp->tr("Diagram"), qApp->tr("Please, choose 'Fi' as "
                                                                      "the variable parameter "), QMessageBox::Close);
            return 0;
        }
        Vainshtein vt(toFt);
        q2=&vt.fi;
        str= "Parameters of Vainshtein method:\n";
        str+="Kappa:\t"+sig.setNum(vt.Kappa)+"\n";
        str+="Gamma:\t"+sig.setNum(__imag__(vt.Gamma))+"\n";
        str+="GammaT:\t"+sig.setNum(__real__(vt.GammaT))+"\n";
        str+="Delta real:\t"+sig.setNum(__real__(vt.Delta))+"\n";
        str+="Delta imag:\t"+sig.setNum(__imag__(vt.Delta))+"\n\n";
//        for (int i=0; i<vt.numCoef[vt.waveType]; i++)
//        {
//            str+="VMN:\t"+sig.setNum(vt.VMN[i])+"\n";
//            str+="MMN:\t"+sig.setNum(vt.MMN[i])+"\n";
//        }
        EIt=vt.eeDelta(vt.Kappa);
        str+="\nS(kap) real:\t"+sig.setNum(__real__(EIt))+"\n";
        str+="S(kap) imag:\t"+sig.setNum(__imag__(EIt))+"\n\n";
        text_cp->append(str);
        vt.coeffs(progress_int);
        GSL_SET_COMPLEX(&vectorE,__real__(vt.Rln[0]),__imag__(vt.Rln[0]));
        text_cp->append(str.setNum(gsl_complex_abs(vectorE)));
        text_cp->append(str.setNum(__real__(vt.Rln[0])));
        text_cp->append(str.setNum(__imag__(vt.Rln[0])));
    }
    if(method==4)
    {
        Diffraction dt(toFt);
        dt.stepByStep(text_cp);
        text_cp->append("\n"+str.setNum(gsl_complex_abs(dt.Refract)));
        text_cp->append(str.setNum(gsl_complex_arg(dt.Refract)));
        text_cp->append(str.setNum(GSL_REAL(dt.Refract)));
        text_cp->append(str.setNum(GSL_IMAG(dt.Refract)));
        dt.matrix(text_cp);
        return 1;
    }
    if(method==5)
    {
        Layer lt(toFt);
        //for (int j=0; j<lt.Num; j++) text_cp->append(str.setNum(lt.Tm[j]));
        text_cp->append("u=:\t"+str.setNum(lt.u[0]));
        text_cp->append("v=:\t"+str.setNum(lt.v[0]));
        //param0=0;
        //paramN*=ft.a;// /ft.b;
        //return 1;
    }
    switch (param)
    {
    case 0 :    //q1 ~ Distance,R
        par=q1;
        param0=param0*(ft.b?ft.b:ft.a); //! @todo Param norming
        paramN=paramN*(ft.b?ft.b:ft.a); //if b!=0 else *(a)
        break;
    case 1 :    //q2 ~ Teta, Fi
        par=q2;
        break;
    case 2 :    //q3 ~ Fi, Distance
        par=q3;
        break;
    }
    dPar=(paramN-param0)/NPt;
    //int j=0;
    __complex__ double bufRES[9];
    double Norm=1,signImag,lastSign=0;
    //text_cp->append("Ref="+str.setNum(__real__(ft.Rln[0])));
    //for (*par = param0 ; *par < (paramN+dPar/2) ; *par += dPar)
    for (int j = 0 ; j<=NPt ; j++)
    {
        for(int i=0; i<3; i++) GSL_SET_COMPLEX(&EItog[i],0,0);
        *par=param0+(double)j*dPar;
        // first filing
        waveSqlModel->insertRows(j,1);	//inserting row in the database
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("q1")),*q1);
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("q2")),*q2);	//	put Fi,Z for Cil
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("q3")),(method > 1 && method<5)?(*q3):(*q3));	//and Teta,Fi for Scope
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("flag_area")),area);
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("flag_method")),method);
        //end of first filing
        QApplication::processEvents();
        progress_int->setValue(j);	// progress-bar
        GSL_SET_COMPLEX(&vectorE,0,0);
        /*	if(method==2) ft.R=ft.b*2/NPt*j;
                        else { tetaDeg=1/NPt*90*j;	//Teta-parameter
                                ft.teta=tetaDeg*M_PI/180;}*/
        //      if(method==3) tetaDeg=1/NPt*180*j;    //?
        //	tetaDeg=1/NPt*360*j;	//It's Fi-degree here
        //	ft.fi=tetaDeg*M_PI/180;
        //if(method==2) ft.R=ft.Z*sin(ft.teta)/cos(ft.teta);
	/*	{ //for teta-parametr
			ft.R=ft.Dist*sin(ft.teta);
			ft.Z=ft.Dist*cos(ft.teta);
		}*/
        /*		if (method==3)
			vainshtein(ft,label_flag);*/
        if(area==3)
        {/*! tab both areas */
            ft.calc(1,method);
            for (int i=0; i<9; i++) bufRES[i]=ft.RES[i];
            ft.calc(2,method);
            for (int i=0; i<9; i++) bufRES[i]+=ft.RES[i];
            for (int i=0; i<3; i++)
            {
                EIt=bufRES[i]+bufRES[i+3]+bufRES[i+6];
                GSL_SET_COMPLEX(&EItog[i],__real__(EIt),__imag__(EIt));
            }
        }
        else
        {/*! Other areas */
            if (method==3)
            {
                GSL_SET_COMPLEX(&EItog[0],0,0);
                EIt=vt.RES[3]*sin(vt.mI*vt.fi);  //i_fi
                GSL_SET_COMPLEX(&EItog[1],__real__(EIt),__imag__(EIt));
                EIt=vt.RES[6]*cos(vt.mI*vt.fi);  //i_Z
                GSL_SET_COMPLEX(&EItog[2],__real__(EIt),__imag__(EIt));
            }
            else
            {
                if (method==5)
                {
                    Layer lt(toFt);
                    GSL_SET_COMPLEX(&EItog[0],0,0);
                    EItog[1]=lt.pole(*par,ft.Z);
                    GSL_SET_COMPLEX(&EItog[2],0,0);
                }
                else
                {
                    //ft.Z=ft.R*cos(*par);
                    //ft.R=ft.R*sin(*par);
                    ft.calc(area,method);
                    for (int i=0; i<3; i++)
                        for(int pr=0; pr<3; pr++)
                            EItog[i]=gsl_complex_add(EItog[i],gsl_complex_rect(__real__(ft.RES[i+3*pr]),__imag__(ft.RES[i+3*pr])));
                    //ft.R=sqrt(pow(ft.R,2)+pow(ft.Z,2));
                }
            }
        }
        for (int i=0;i<3;i++) //checking for NaN
        {
            if(GSL_REAL(EItog[i])!=GSL_REAL(EItog[i])) GSL_SET_REAL(&EItog[i],0);
            if(GSL_IMAG(EItog[i])!=GSL_IMAG(EItog[i])) GSL_SET_IMAG(&EItog[i],0);
        }
        /*! absolute value & argument of complex vector */
        for (int i=0;i<3;i++) vectorE=gsl_complex_add(vectorE,gsl_complex_pow_real(EItog[i],2));
        //for (int i=0;i<3;i++) text_cp->append(str.setNum(GSL_REAL(EItog[i]))+"\t"+sig.setNum(GSL_IMAG(EItog[i])));
        vectorE=gsl_complex_sqrt(vectorE);
        ampl=gsl_complex_abs(vectorE);	//Amplitude
        if(j==0) Norm=ampl;
        signImag=GSL_IMAG(vectorE);	//Argument
        if(lastSign*signImag<0 && signImag>0) sopr*=-1;
        lastSign=signImag;
        vectorE=gsl_complex_mul_real(vectorE,sopr/Norm);
        arg=gsl_complex_arg(vectorE);
        /*! filling Database new Row */
        //vectorE=gsl_complex_div_real(vectorE,Norm);
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("Amp")),ampl/Norm);   //Amplitude after norming
//        waveSqlModel->setData(waveSqlModel->index(j,Base.key("Amp")),ampl);   //Amplitude without norming
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("Arg")),arg);
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("realE")),GSL_REAL(vectorE));
        waveSqlModel->setData(waveSqlModel->index(j,Base.key("imagE")),GSL_IMAG(vectorE));
        for(int pr=0;pr<9;pr++) //grad_div, rot and j
        {
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+Base.key("rot_q1_re")),__real__(ft.RES[pr]));//component writing
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+Base.key("rot_q1_im")),__imag__(ft.RES[pr]));
        }
        for (int pr=0;pr<3;pr++)	//pr - number of coordinate; 0:R, 1: teta, 2: fi
        {
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+Base.key("Eq1_re")),GSL_REAL(EItog[pr]));	//component writing
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+Base.key("Eq1_im")),GSL_IMAG(EItog[pr]));
        }
        waveSqlModel->submitAll();	//writing data into database
        //j++;
    }
    //end of evaluating
    waveTable->resizeColumnsToContents();
    return 1;
}

void MainWindowImpl::on_but_diasec_clicked()
{
    isSec=1;
    int pr,NPt,sopr=1;	//NPt: number of points through teta; sopr: sign of image patr
    double ampl,arg;    //control of sopr-change
    double param0,paramN, dPar;
    Structure *toFt;
    __complex__ double EIt; //complex coordinates of tensity vector
    gsl_complex EItog[3], vectorE; 	//complex coordinates of tensity vector
    toFt=&ft;
    initCalc(); //Initialization
    on_but_printParam_clicked(); //print
    NPt=boxNdiag->value();
    progress_int->setMaximum(NPt*NPt);
    //begin of evaluating
    param0=boxParam0->value();
    paramN=boxParamN->value();
    param0=param0*ft.b;
    paramN=paramN*ft.b;
    dPar=(paramN-param0)/NPt;
    int j=0;
    __complex__ double bufRES[9];
    gsl_complex stage;
    double Norm=1,signImag,lastSign=0;
    for (int m=0 ; m < (NPt+1) ; m++)
    {
        for (int n=0 ; n < (NPt+1) ; n++)
        {
            *q1=sqrt(pow(m*dPar,2)+pow(n*dPar,2));
            GSL_SET_COMPLEX(&stage,n,m);
            *q2=gsl_complex_arg(stage);
            progress_int->setValue(j);	// progress-bar
            waveSqlModel->insertRows(j,1);	//inserting row in the database
            GSL_SET_COMPLEX(&vectorE,0,0);
            if(area==3)
            {/*! tab both areas */
                ft.calc(1,method);
                for (int i=0; i<9; i++) bufRES[i]=ft.RES[i];
                ft.calc(2,method);
                for (int i=0; i<9; i++) bufRES[i]+=ft.RES[i];
                for (int i=0; i<3; i++)
                {
                    EIt=bufRES[i]+bufRES[i+3]+bufRES[i+6];
                    GSL_SET_COMPLEX(&EItog[i],__real__(EIt),__imag__(EIt));
                }
            }
            else
            {/*! This is a check then area=0 or a tab of single area */
                ft.calc(area,method);
                for (int i=0; i<3; i++)
                {
                    EIt=ft.RES[i]+ft.RES[i+3]+ft.RES[i+6];
                    GSL_SET_COMPLEX(&EItog[i],__real__(EIt),__imag__(EIt));
                }
            }
            /*! absolute value & argument of complex vector */
            for (int i=0;i<3;i++) vectorE=gsl_complex_add(vectorE,gsl_complex_pow_real(EItog[i],2));
            vectorE=gsl_complex_sqrt(vectorE);
            ampl=gsl_complex_abs(vectorE);	//Amplitude
            if(j==0) Norm=ampl;
            waveSqlModel->setData(waveSqlModel->index(j,32),ampl/Norm);   //Amplitude after norming
            signImag=GSL_IMAG(vectorE);	//Argument
            if(lastSign*signImag<0 && signImag>0) sopr*=-1;
            lastSign=signImag;
            vectorE=gsl_complex_mul_real(vectorE,sopr/Norm);
            arg=gsl_complex_arg(vectorE);
            waveSqlModel->setData(waveSqlModel->index(j,33),arg);	//argument after correcting
            /*! filling Database new Row */
            waveSqlModel->setData(waveSqlModel->index(j,1),GSL_REAL(vectorE));
            waveSqlModel->setData(waveSqlModel->index(j,2),GSL_IMAG(vectorE));
            for(pr=0;pr<9;pr++) //grad_div, rot and j
            {
                waveSqlModel->setData(waveSqlModel->index(j,2*pr+12),__real__(ft.RES[pr]));//writing of real component
                waveSqlModel->setData(waveSqlModel->index(j,2*pr+13),__imag__(ft.RES[pr]));//writing of imag component
            }
            for (pr=0;pr<3;pr++)	//pr - number of coordinate; 0:R, 1: teta, 2: fi
            {
                waveSqlModel->setData(waveSqlModel->index(j,2*pr+3),GSL_REAL(EItog[pr]));	//writing of real component
                waveSqlModel->setData(waveSqlModel->index(j,2*pr+4),GSL_IMAG(EItog[pr]));	//writing of imag component
            }
            waveSqlModel->setData(waveSqlModel->index(j,9),*q1);
            waveSqlModel->setData(waveSqlModel->index(j,10),*q2);
            waveSqlModel->setData(waveSqlModel->index(j,11),*q3);
            waveSqlModel->setData(waveSqlModel->index(j,30),area);
            waveSqlModel->setData(waveSqlModel->index(j,31),method);
            waveSqlModel->submitAll();	//writing data into database
            j++;
        }
    }
    //end of evaluating
    waveTable->resizeColumnsToContents();
}

void MainWindowImpl::on_but_Test_clicked()
{
    QString str,sig,sti;
    int pr,NPt,sopr=1;	//NPt: number of points through teta; sopr: sign of image patr
    double ampl,arg;    //control of sopr-change
    double param0,paramN, dPar;
    Structure *toFt;
    __complex__ double EIt; //complex coordinates of tensity vector
    gsl_complex EItog[3], bufEItog[3], vectorE; 	//complex coordinates of tensity vector
    toFt=&ft;
    initCalc(); //Initialization
    on_but_printParam_clicked(); //print
    NPt=boxNdiag->value();
    progress_int->setMaximum(NPt);
    //begin of evaluating
    param0=boxParam0->value();
    paramN=boxParamN->value();
    //if(method==4) diffraction(toFt,text_cp);
    switch (param)
    {
    case 0 :    //q1 ~ Distance,R
        par=q1;
        param0*=ft.b;
        paramN*=ft.b;
        break;
    case 1 :    //q2 ~ Teta, Fi
        par=q2;
        param0=param0; // /180*M_PI;
        paramN=paramN; // /180*M_PI;
        break;
    case 2 :    //q3 ~ Fi, Distance
        par=q3;
        param0=param0; // /180*M_PI;
        paramN=paramN; // /180*M_PI;
        break;
    }
    dPar=(paramN-param0)/NPt;
    int j=0;
    __complex__ double bufRES[9];
    double Norm=1,buf,signImag,lastSign=0;
    buf=ft.R;
    for (*par = param0 ; *par <= paramN ; *par += dPar)
    {
        progress_int->setValue(j);	// progress-bar
        waveSqlModel->insertRows(j,1);	//inserting row in the database
        GSL_SET_COMPLEX(&vectorE,0,0);
        ft.R=buf;
        //tab both areas
        ft.calc(1,0);
        for (int i=0; i<9; i++) bufRES[i]=ft.RES[i];
        ft.calc(2,0);
        for (int i=0; i<9; i++) bufRES[i]+=ft.RES[i];
        for (int i=0; i<3; i++)
        {
            EIt=bufRES[i]+bufRES[i+3]+bufRES[i+6];
            GSL_SET_COMPLEX(&bufEItog[i],__real__(EIt),__imag__(EIt));
        }
        ft.Z=ft.R*cos(ft.teta);
        ft.R*=sin(ft.teta);
        ft.calc(1,2);
        for (int i=0; i<9; i++) bufRES[i]=ft.RES[i];
        ft.calc(2,2);
        for (int i=0; i<9; i++) bufRES[i]+=ft.RES[i];
        for (int i=0; i<3; i++)
        {
            EIt=bufRES[i]+bufRES[i+3]+bufRES[i+6];
            GSL_SET_COMPLEX(&EItog[i],__real__(EIt),__imag__(EIt));
        }
        EItog[0] = gsl_complex_sub (bufEItog[2],EItog[1]);
        /*! \fn absolute value & argument of complex vector */
        for (int i=0;i<3;i++) vectorE=gsl_complex_add(vectorE,gsl_complex_pow_real(EItog[i],2));
        vectorE=gsl_complex_sqrt(vectorE);
        ampl=gsl_complex_abs(vectorE);	//Amplitude
        if(j==0) Norm=ampl;
        waveSqlModel->setData(waveSqlModel->index(j,32),ampl/Norm);   //Amplitude after norming
        signImag=gsl_complex_arg(EItog[1]);			//argument
        if(lastSign*signImag<0 && signImag>0) sopr*=-1;
        lastSign=signImag;
        vectorE=gsl_complex_mul_real(vectorE,sopr/Norm);
        arg=gsl_complex_arg(vectorE);
        waveSqlModel->setData(waveSqlModel->index(j,33),arg);	//argument after correcting
        /*! \fn filling Database new Row*/
        waveSqlModel->setData(waveSqlModel->index(j,1),GSL_REAL(vectorE));
        waveSqlModel->setData(waveSqlModel->index(j,2),GSL_IMAG(vectorE));
        for(pr=0;pr<9;pr++) //grad_div, rot and j
        {
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+12),__real__(ft.RES[pr]));//writing of real component
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+13),__imag__(ft.RES[pr]));//writing of imag component
        }
        for (pr=0;pr<3;pr++)	//pr - number of coordinate; 0:R, 1: teta, 2: fi
        {
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+3),GSL_REAL(EItog[pr]));	//writing of real component
            waveSqlModel->setData(waveSqlModel->index(j,2*pr+4),GSL_IMAG(EItog[pr]));	//writing of imag component
        }
        waveSqlModel->setData(waveSqlModel->index(j,9),*q1);
        waveSqlModel->setData(waveSqlModel->index(j,10),*q2);	//	put Fi,Z for Cil
        waveSqlModel->setData(waveSqlModel->index(j,11),(method==2 || method==4)?(*q3):(*q3));	//and Teta,Fi for Scope
        waveSqlModel->setData(waveSqlModel->index(j,30),area);
        waveSqlModel->setData(waveSqlModel->index(j,31),method);
        waveSqlModel->submitAll();	//writing data into database
        j++;
    }
    //
}

void MainWindowImpl::on_but_printParam_clicked()
{
    QString str,sig;
    str= "Input parameters of Diagram:\n";
    str+="Frequency:\t"+sig.setNum(ft.f0)+"\trad/c\n";
    str+="a: \t"+sig.setNum(ft.a)+"\tm\n";
    str+="b: \t"+sig.setNum(ft.b)+"\tm\n";
    str+="k: \t"+sig.setNum(ft.k)+"\tm\n";
    str+="Distantion: \t"+sig.setNum(ft.Dist)+"\tm\n";
    str+="alfa1:\t"+sig.setNum(ft.alfa1)+"\t1/m\n";
    str+="alfa2: i*\t"+sig.setNum(__imag__(ft.alfa2))+"\t1/m\n";
    str+="beta: \t"+sig.setNum(ft.beta)+"\t1/m\n";
    str+="mI: \t"+sig.setNum(ft.mI)+"\t";
    str+="nI: \t"+sig.setNum(ft.nI)+"\t";
    str+="wT: \t"+sig.setNum(ft.waveType)+"\n";
    text_cp->append(str);
    ft.textParam=str;
}

